package com.zb.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zb.entity.*;
import com.zb.mapper.ZjWorkClientStrategyMapper;
import com.zb.result.PageUtil;
import com.zb.service.*;
import com.zb.vo.WorkClientStrategyVo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 工单客服分派策略表 服务实现类
 * </p>
 *
 * @author WEN
 * @since 2023-09-27
 */
@Service
public class ZjWorkClientStrategyServiceImpl extends ServiceImpl<ZjWorkClientStrategyMapper, ZjWorkClientStrategy> implements ZjWorkClientStrategyService {
    @Resource
    private ZjWorkClientStrategyMapper workClientStrategyMapper;
    @Resource
    private ZjWorkClientStrategyConditionService workClientStrategyConditionService;
    @Resource
    private ZjWorkClientStrategyEmpService workClientStrategyEmpService;
    @Resource
    private ZjWorkModuleService workModuleService;
    @Resource
    private ZjWorkOrderService workOrderService;

    // 新增或修改工单客服分配策略
    @Override
    @Transactional
    public void save(Long custAccId, WorkClientStrategyVo clientStrategyVo) {
        Assert.isTrue(null == workClientStrategyMapper.existByName(custAccId, clientStrategyVo.getId(), clientStrategyVo.getName()), "分配客服规则名称已重复");
        ZjWorkClientStrategy strategy = new ZjWorkClientStrategy();
        BeanUtils.copyProperties(clientStrategyVo, strategy);
        strategy.setDisabled(clientStrategyVo.getStatus());
        if (null != strategy.getId()) {
            this.updateById(strategy);
        } else {
            strategy.setId(IdWorker.getId());
            strategy.setCustAccId(custAccId);
            strategy.setWeight(null == strategy.getWeight()? 0 : strategy.getWeight());
            this.save(strategy);
        }
        workClientStrategyConditionService.save(custAccId, strategy.getId(), clientStrategyVo.getConditionVos(), clientStrategyVo.getDelConditionIds());
        workClientStrategyEmpService.save(custAccId, strategy.getId(), clientStrategyVo.getServiceIds());
    }

    // 根据ID获取工单客服分配规则详情
    @Override
    public WorkClientStrategyVo getDetail(Long id) {
        ZjWorkClientStrategy strategy = this.getById(id);
        Assert.isTrue(null != strategy, "客服分配规则ID参数[" + id + "]的数据不存在");

        WorkClientStrategyVo vo = new WorkClientStrategyVo();
        BeanUtils.copyProperties(strategy, vo);
        vo.setStatus(strategy.getDisabled());
        vo.setConditionVos(workClientStrategyConditionService.getParentConditionByWorkClientStrategyId(id));
        vo.setServiceIds(workClientStrategyEmpService.getValIdByWorkClientStrategyId(id).stream().map(ZjWorkClientStrategyEmp::getValId).toList());
        return vo;
    }

    // 批量启用或禁用工单客服分配规则
    @Override
    public void updateDisableBatchById(List<Long> idList, boolean status) {
        workClientStrategyMapper.updateDisableBatchById(idList, status);
    }

    // 批量删除工单客服分配规则
    @Override
    @Transactional
    public void deleteBatchById(List<Long> ids) {
        List<ZjWorkModule> moduleList = workModuleService.getByWorkClientStrategyId(ids);
        if (CollectionUtils.isNotEmpty(moduleList)) {
            QueryWrapper<ZjWorkClientStrategy> wrapper = new QueryWrapper<>();
            wrapper.select("name");
            wrapper.in("id", moduleList.stream().map(ZjWorkModule::getWorkClientStrategyId).distinct().toList());
            String names = this.list(wrapper).stream().map(ZjWorkClientStrategy::getName).collect(Collectors.joining("、"));
            Assert.isTrue(false, "客服分配规则[" + names + "]已与工单模块[" + moduleList.stream().map(ZjWorkModule::getName).distinct().collect(Collectors.joining("、")) + "]关联使用中，不可删除");
        }
        workClientStrategyEmpService.removeByIds(ids);
        workClientStrategyConditionService.deleteBatchByWorkClientStrategyIds(ids);
        this.removeByIds(ids);
    }

    // 根据ID获取
    @Override
    public List<String> getNameByIds(List<Long> ids) {
        if (null == ids || ids.isEmpty()) {
            return new ArrayList<>();
        }
        QueryWrapper<ZjWorkClientStrategy> wrapper = new QueryWrapper<>();
        wrapper.select("name");
        wrapper.in("id", ids);
        return this.list(wrapper).stream().map(ZjWorkClientStrategy::getName).toList();
    }

    // 根据客服分配策略获取客服ID
    @Override
    public Long getEmpIdById(WorkDispatchConditionVo workDispatchConditionVo) {
        Long empId = 0L;
        boolean executeDispatch = workClientStrategyConditionService.isExecuteDispatch(workDispatchConditionVo);
        if (!executeDispatch) {
            return empId;
        }
        ZjWorkClientStrategy clientStrategy = this.getById(workDispatchConditionVo.getId());
        List<Long> empIds = workClientStrategyEmpService.getEmpIdByEmpTypeAndWorkClientStrategyId(clientStrategy.getEmpType(), clientStrategy.getId());
        if (CollectionUtils.isEmpty(empIds)) {
            return empId;
        }
        // 平均、随机
        if (1 == clientStrategy.getType() || 2 == clientStrategy.getType()) {
            List<EmpOrderCountVo> empOrderCountVos = workOrderService.getEmpOrderCountByEmpIds(empIds);
            if (CollectionUtils.isEmpty(empOrderCountVos)) {
                empId = empIds.get(0);
                return empId;
            }
            for (Long id : empIds) {
                if (empOrderCountVos.stream().noneMatch(empOrderCountVo -> Objects.equals(empOrderCountVo.getEmpId(), id))) {
                    empOrderCountVos.add(new EmpOrderCountVo(id, 0));
                }
            }
            empOrderCountVos.sort((s, s1) -> s.getQty().compareTo(s1.getQty()));
            // 平均
            if (1 == clientStrategy.getType()) {
                empId =  empOrderCountVos.get(0).getEmpId();
                return empId;
            }
            // 随机
            if (2 == clientStrategy.getType()) {
                List<Long> orderEmpIds = empOrderCountVos.stream().map(EmpOrderCountVo::getEmpId).toList();
                empId = orderEmpIds.get((int) (Math.random() * orderEmpIds.size()));
                return empId;
            }
        }
        // 熟客
        if (3 == clientStrategy.getType()) {
            List<EmpOrderCountVo> orderCountVoList = workOrderService.getHistoryOrderLastEmpIdByEmpIds(empIds);
            orderCountVoList.sort((s, s1) -> s.getQty().compareTo(s1.getQty()));
            empId = orderCountVoList.get(0).getEmpId();
            return empId;
        }
        return empId;
    }

    // 分页获取客服分配规则列表
    @Override
    public Map<String, Object> workClientStrategyPageSelect(Long custAccId, SelectVo selectVo) {
        PageUtil.setSelectPageLimit(selectVo);
        QueryWrapper<ZjWorkClientStrategy> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("weight", "gmt_update");
        wrapper.select("id", "name");
        wrapper.eq("cust_acc_id", custAccId).eq("is_disabled", false);
        if (StringUtils.isNotBlank(selectVo.getName())) {
            wrapper.like("name", selectVo.getName());
        }
        Page<ZjWorkClientStrategy> page = this.page(new Page<>(selectVo.getPage(), selectVo.getLimit()), wrapper);
        return PageUtil.pageList(page.getCurrent(), page.getSize(), page.getTotal(), page.getRecords().stream().map(client -> {
            return new SelectResultVo(client.getId(), client.getName());
        }).toList());
    }


    public static void main(String[] args) {
        List<Integer> qtys = new ArrayList<>();
        qtys.add(9);
        qtys.add(3);
        qtys.add(3);
        qtys.add(8);
        qtys.add(2);
        qtys.add(2);
        qtys.add(1);
        qtys.add(1);
        for (int i = 0; i < 8; i++) {
            int random =(int) (Math.random() * qtys.size());
            System.out.println(random);
        }
    }
}
